﻿using EasyI18n.Api.Infrastructure.DataPersistence.MongoDb;
using EasyI18n.Api.Infrastructure.DataPersistence.MongoDb.Entities;
using EasyI18n.Api.Primary.Bases;
using EasyI18n.Api.Primary.Contracts.Bases;
using EasyI18n.Api.Primary.Contracts.ProjectContracts;
using EasyI18n.Api.Realization.Bases;
using FluentValidation;
using Mediator.Net.Context;
using MongoDB.Bson;
using MongoDB.Driver;
using Shouldly;

namespace EasyI18n.Api.Realization.Handlers.ProjectHandlers;

public class CreateProjectHandler(
    ICurrentSingle<SystemUser> currentUser,
    IDocumentAccessor<Project> projectDocs,
    IDocumentAccessor<ProjectUser> projectUserDocs)
    : ICreateProjectContract
{
    public async Task Handle(IReceiveContext<CreateProjectCommand> context, CancellationToken cancellationToken)
    {
        var project = context.Message.MapToSource(new Project());
        // var user = await currentUser.QueryAsync(cancellationToken);
        var user = new SystemUser(){Id = ObjectId.GenerateNewId()};

        project.CreatedBy = user.Id;
        project.UpdatedBy = user.Id;
        var projectFilter =
            await projectDocs.Collection.FindAsync(e => e.Name == project.Name, cancellationToken: cancellationToken);
        if (await projectFilter.AnyAsync(cancellationToken))
        {
            throw new BusinessException("项目名重复", BusinessExceptionTypeEnum.DataDuplication);
        }

        await projectDocs.Collection.InsertOneAsync(project, new InsertOneOptions(), cancellationToken);
        await projectUserDocs.Collection.InsertOneAsync(new ProjectUser()
        {
            ProjectId = project.Id,
            UserId = user.Id,
        }, new InsertOneOptions(), cancellationToken);
    }

    public void Validate(ContractValidator<CreateProjectCommand> validator)
    {
        validator.RuleFor(e => e.Name)
            .NotEmpty()
            .WithMessage("项目名不能为空");
    }

    public void Test(TestContext<CreateProjectCommand> context)
    {
        var newProjectCase = context.CreateTestCase();
        newProjectCase.CurrentUser = new SystemUser().Faker();
        newProjectCase.Message = new CreateProjectCommand().Faker();
        newProjectCase.Assert = result =>
        {
            result.Exception.ShouldBeNull();
            return Task.CompletedTask;
        };

        var duplicateProjectCase = context.CreateTestCase();
        duplicateProjectCase.Message = newProjectCase.Message;
        duplicateProjectCase.CurrentUser = newProjectCase.CurrentUser;
        duplicateProjectCase.Assert = result =>
        {
            var exception = result.Exception as BusinessException;
            exception.ShouldNotBeNull();
            exception.Type.ShouldBe(BusinessExceptionTypeEnum.DataDuplication);
            return Task.CompletedTask;
        };
    }
}